package com.evil.application.convert;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSON;
import com.evil.account.api.RemoteDepartmentService;
import com.evil.account.api.RemoteRoleService;
import com.evil.account.api.RemoteUserDepartmentService;
import com.evil.account.api.RemoteUserService;
import com.evil.application.enums.form.control.ControlCodeEnum;
import com.evil.application.enums.order.OrderSpecialControlEnum;
import com.evil.application.pojo.dto.form.control.ControlBaseInfoDTO;
import com.evil.application.pojo.dto.form.control.code.ControlDTO;
import com.evil.application.pojo.dto.form.control.option.FormOptionRespDTO;
import com.evil.application.pojo.dto.form.control.related.ControlRelatedDTO;
import com.evil.application.pojo.entity.*;
import com.evil.application.service.*;
import com.evil.application.util.ApplicationUtil;
import com.evil.application.util.OrderDataUtil;
import com.evil.common.account.dto.FindByNameAndEIdReqDTO;
import com.evil.common.account.dto.FindByNamesAndEIdReqDTO;
import com.evil.common.account.dto.department.DepartmentBaseRespDTO;
import com.evil.common.account.dto.role.RoleBaseRespDTO;
import com.evil.common.account.dto.user.UserBaseRespDTO;
import com.evil.common.account.dto.user.UserEnterpriseBaseDTO;
import com.evil.common.account.util.LoginUtil;
import com.evil.common.activiti.enums.HandleTypeEnum;
import com.evil.common.application.dto.form.SpecialControlConfigDTO;
import com.evil.common.application.dto.form.control.ControlBaseDTO;
import com.evil.common.application.dto.judge.JudgeOr;
import com.evil.common.application.dto.judge.JudgeSourceDTO;
import com.evil.common.application.dto.order.data.ControlDataDTO;
import com.evil.common.application.dto.order.data.ControlDataValueDTO;
import com.evil.common.application.dto.order.data.SpecialControlData;
import com.evil.common.application.dto.order.node.OrderNodesDTO;
import com.evil.common.application.dto.permission.app.AppPermissionDTO;
import com.evil.common.application.dto.permission.app.AppPermissionSourceDTO;
import com.evil.common.application.dto.process.node.NodeBaseDTO;
import com.evil.common.application.enums.ApplicationVersionEnum;
import com.evil.common.application.enums.order.OrderProcessStatusEnum;
import com.evil.common.core.enums.BaseEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.core.util.StreamUtil;
import com.evil.common.core.util.spring.SpringUtils;
import com.evil.common.family.dto.FindByIdsReqDTO;
import com.evil.common.file.dto.FileRespDTO;
import com.evil.file.api.RemoteFileService;
import jakarta.validation.Valid;
import lombok.Getter;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单数据转换 处理缓存
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
public class DataConvert {

    private final Long enterpriseId;

    private final Long userId;

    // region function
    private RemoteUserService remoteUserService;

    private RemoteDepartmentService remoteDepartmentService;

    private RemoteUserDepartmentService remoteUserDepartmentService;

    private RemoteRoleService remoteRoleService;

    private RemoteFileService remoteFileService;

    private ApplicationInfoService applicationInfoService;

    private ApplicationFormService applicationFormService;

    private ApplicationFormControlService applicationFormControlService;

    private ApplicationFormControlRelatedService applicationFormControlRelatedService;

    private FormControlOptionService formControlOptionService;

    private ApplicationProcessService applicationProcessService;

    private ApplicationProcessNodeService applicationProcessNodeService;

    private ApplicationPermissionService applicationPermissionService;

    private ApplicationJudgeService applicationJudgeService;

    private ApplicationOrderService applicationOrderService;

    private ApplicationOrderDataService applicationOrderDataService;

    private ApplicationOrderNodeHandlerService applicationOrderNodeHandlerService;
    // endregion

    // region map

    /**
     * 用户基础信息 key=userId
     */
    @Getter
    private Map<Long, UserBaseRespDTO> userBaseMap;

    /**
     * 用户基础信息 key=name
     */
    @Getter
    private Map<String, UserBaseRespDTO> userBaseMap_Name;

    /**
     * 部门基础信息 key=departmentId
     */
    @Getter
    private Map<Long, DepartmentBaseRespDTO> departmentBaseMap;

    /**
     * 部门基础信息 key=departmentId
     */
    @Getter
    private Map<String, DepartmentBaseRespDTO> departmentBaseMap_Name;

    /**
     * 部门基础信息 key=userId
     */
    @Getter
    private Map<Long, List<DepartmentBaseRespDTO>> userDepartmentBaseMap;

    /**
     * 角色基础信息 key=roleId
     */
    @Getter
    private Map<Long, RoleBaseRespDTO> roleBaseMap;

    /**
     * 文件基础信息 key=fileCode
     */
    @Getter
    private Map<Long, FileRespDTO> fileMap;

    /**
     * 文件基础信息 key=fileCode
     */
    @Getter
    private Map<String, FileRespDTO> fileCodeMap;

    /**
     * 应用 key=appId
     */
    @Getter
    private Map<Long, ApplicationInfo> appMap;

    /**
     * 应用 key=appId
     */
    @Getter
    private Map<String, ApplicationInfo> appKeyMap;

    /**
     * 应用 key=formId
     */
    @Getter
    private Map<Long, ApplicationForm> formMap;

    /**
     * 应用 key=appId
     */
    @Getter
    private Map<Long, ApplicationForm> appReleaseFormMap;

    /**
     * 控件 key=controlId
     */
    @Getter
    private Map<Long, ApplicationFormControl> controlMap;

    /**
     * 控件 key=controlId
     */
    @Getter
    private Map<Long, ControlDTO> controlDTOMap;

    /**
     * 控件 key=controlId
     */
    @Getter
    private Map<Long, ControlBaseDTO> controlBaseMap;

    /**
     * 控件 key=controlId
     */
    @Getter
    private Map<Long, ControlBaseInfoDTO> controlBaseInfoMap;

    /**
     * 控件关联 key=controlId
     */
    @Getter
    private Map<Long, List<ControlRelatedDTO>> controlRelatedBasesMap;

    /**
     * 选项值 key=optionId
     */
    @Getter
    private Map<Long, FormOptionRespDTO> optionMap;

    /**
     * 控件选项值 key=controlId
     */
    @Getter
    private Map<Long, List<FormOptionRespDTO>> controlOptionMap;

    /**
     * 流程信息 key=processId
     */
    @Getter
    private Map<Long, ApplicationProcess> processMap;

    /**
     * 流程信息 key=processId
     */
    @Getter
    private Map<Long, ApplicationProcess> appReleaseProcessMap;

    /**
     * 节点基础信息 key=nodeId
     */
    @Getter
    private Map<Long, NodeBaseDTO> nodeMap;

    /**
     * 应用权限 key=SourceDTO
     */
    @Getter
    private Map<AppPermissionSourceDTO, List<AppPermissionDTO>> sourceAppPermissionsMap;

    /**
     * 筛选条件 key=SourceDTO
     */
    @Getter
    private Map<JudgeSourceDTO, List<JudgeOr>> sourcesJudgeMap;

    /**
     * 订单
     */
    @Getter
    private Map<Long, ApplicationOrder> orderMap;

    /**
     * 应用选项
     */
    @Getter
    private Map<Long, FormOptionRespDTO> orderQuoteMap;

    /**
     * 订单节点处理人
     */
    @Getter
    private Map<String, List<ApplicationOrderNodeHandler>> orderNodeHandlerMap;
    // endregion

    // region init
    public DataConvert(LoginUtil loginUtil) {
        this.enterpriseId = loginUtil.getLoginEnterpriseId();
        this.userId = loginUtil.getLoginUserId();
    }

    public DataConvert(Long enterpriseId, Long userId) {
        this.enterpriseId = enterpriseId;
        this.userId = userId;
    }

    public DataConvert initUserMap() {
        this.remoteUserService = SpringUtils.getBean(RemoteUserService.class);
        this.userBaseMap = new HashMap<>();
        this.userBaseMap_Name = new HashMap<>();
        return this;
    }

    public DataConvert initDepartmentMap() {
        this.remoteDepartmentService = SpringUtils.getBean(RemoteDepartmentService.class);
        this.departmentBaseMap = new HashMap<>();
        this.departmentBaseMap_Name = new HashMap<>();
        this.userDepartmentBaseMap = new HashMap<>();
        return this;
    }

    public DataConvert initRoleMap() {
        this.remoteRoleService = SpringUtils.getBean(RemoteRoleService.class);
        this.roleBaseMap = new HashMap<>();
        return this;
    }

    public DataConvert initFileMap() {
        this.remoteFileService = SpringUtils.getBean(RemoteFileService.class);
        this.fileMap = new HashMap<>();
        this.fileCodeMap = new HashMap<>();
        return this;
    }

    public DataConvert initAppMap() {
        this.applicationInfoService = SpringUtils.getBean(ApplicationInfoService.class);
        this.appMap = new HashMap<>();
        this.appKeyMap = new HashMap<>();
        return this;
    }

    public DataConvert initFormMap() {
        this.applicationFormService = SpringUtils.getBean(ApplicationFormService.class);
        this.formMap = new HashMap<>();
        this.appReleaseFormMap = new HashMap<>();
        return this;
    }

    public DataConvert initControlMap() {
        this.applicationFormControlService = SpringUtils.getBean(ApplicationFormControlService.class);
        this.controlMap = new HashMap<>();
        this.controlDTOMap = new HashMap<>();
        this.controlBaseMap = new HashMap<>();
        this.controlBaseInfoMap = new HashMap<>();
        return this;
    }

    public DataConvert initControlRelatedBasesMap() {
        this.applicationFormControlRelatedService = SpringUtils.getBean(ApplicationFormControlRelatedService.class);
        this.controlRelatedBasesMap = new HashMap<>();
        return this;
    }

    public DataConvert initOptionMap() {
        this.formControlOptionService = SpringUtils.getBean(FormControlOptionService.class);
        this.optionMap = new HashMap<>();
        this.controlOptionMap = new HashMap<>();
        return this;
    }

    public DataConvert initProcessMap() {
        this.applicationProcessService = SpringUtils.getBean(ApplicationProcessService.class);
        this.processMap = new HashMap<>();
        this.appReleaseProcessMap = new HashMap<>();
        return this;
    }

    public DataConvert initNodeMap() {
        this.applicationProcessNodeService = SpringUtils.getBean(ApplicationProcessNodeService.class);
        this.nodeMap = new HashMap<>();
        return this;
    }

    public DataConvert initPermissionMap() {
        this.applicationPermissionService = SpringUtils.getBean(ApplicationPermissionService.class);
        this.sourceAppPermissionsMap = new HashMap<>();
        return this;
    }

    public DataConvert initJudgeMap() {
        this.applicationJudgeService = SpringUtils.getBean(ApplicationJudgeService.class);
        this.sourcesJudgeMap = new HashMap<>();
        return this;
    }

    public DataConvert initOrderMap() {
        this.applicationOrderService = SpringUtils.getBean(ApplicationOrderService.class);
        this.orderMap = new HashMap<>();
        return this;
    }

    public DataConvert initOrderQuoteMap() {
        this.applicationOrderDataService = SpringUtils.getBean(ApplicationOrderDataService.class);
        this.orderQuoteMap = new HashMap<>();
        return this;
    }

    public DataConvert initOrderNodeHandlerMap() {
        this.applicationOrderNodeHandlerService = SpringUtils.getBean(ApplicationOrderNodeHandlerService.class);
        this.orderNodeHandlerMap = new HashMap<>();
        return this;
    }
    // endregion

    // region 用户

    /**
     * 获取用户列表
     *
     * @param userId userId
     * @return UserBaseRespDTO 列表
     */
    public UserBaseRespDTO getUserBase(Long userId) {
        return this.convert(
                userBaseMap,
                userId,
                unExist -> remoteUserService.findBaseById(unExist)
        );
    }

    /**
     * 获取用户列表
     *
     * @param name name
     * @return UserBaseRespDTO 列表
     */
    public UserBaseRespDTO getUserBaseByName(String name) {
        return this.convert(
                userBaseMap_Name,
                name,
                unExist -> remoteUserService.findBaseByName(FindByNameAndEIdReqDTO.filter(this.enterpriseId, unExist))
        );
    }

    /**
     * 获取用户列表
     *
     * @param userIds       userIds
     * @param filterDeleted filterDeleted
     * @return UserBaseRespDTO 列表
     */
    public List<UserBaseRespDTO> getUserBases(Collection<Long> userIds, boolean filterDeleted) {
        return this.convertList(
                userBaseMap,
                userIds,
                list -> remoteUserService.findBaseMapByIds(FindByIdsReqDTO.build(userIds, filterDeleted))
        );
    }

    /**
     * 获取用户列表
     *
     * @param names names
     * @return UserBaseRespDTO 列表
     */
    public List<UserBaseRespDTO> getUserBasesByNames(Collection<String> names) {
        return this.convertList(
                userBaseMap_Name,
                names,
                list -> remoteUserService.findBaseMapByNames(FindByNamesAndEIdReqDTO.filter(this.enterpriseId, list))
        );
    }

    /**
     * 获取用户列表
     *
     * @param userIds       userIds
     * @param filterDeleted filterDeleted
     * @return DepartmentBaseRespDTO 列表
     */
    public Map<Long, UserBaseRespDTO> getUserBasesMap(Collection<Long> userIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getUserBases(userIds, filterDeleted), UserBaseRespDTO::getUserId);
    }

    /**
     * 获取默认内容的用户信息列表
     *
     * @param permissions permissions
     * @return List
     */
    public List<UserBaseRespDTO> getUserBaseList(List<AppPermissionDTO> permissions) {
        Map<Integer, Map<Long, ?>> integerMapMap = applicationPermissionService
                .convertTypeTarget(applicationPermissionService.convertAppPermission(permissions));

        List<UserBaseRespDTO> userBases = new ArrayList<>();
        permissions.forEach(p -> {
            if (integerMapMap.containsKey(p.getPermissionType())) {
                Map<Long, ?> targetMap = integerMapMap.get(p.getPermissionType());
                if (targetMap.containsKey(p.getTargetId())) {
                    userBases.add((UserBaseRespDTO) targetMap.get(p.getTargetId()));
                }
            }
        });
        return userBases;
    }
    // endregion

    // region 部门

    /**
     * 获取部门列表
     *
     * @param departmentId departmentId
     * @return DepartmentBaseRespDTO
     */
    public DepartmentBaseRespDTO getDepartmentBase(Long departmentId) {
        return this.convert(
                departmentBaseMap,
                departmentId,
                unExist -> remoteDepartmentService.findBaseById(unExist)
        );
    }

    /**
     * 获取部门列表
     *
     * @param name name
     * @return DepartmentBaseRespDTO
     */
    public DepartmentBaseRespDTO getDepartmentBaseByName(String name) {
        return this.convert(
                departmentBaseMap_Name,
                name,
                unExist -> remoteDepartmentService.findBaseByName(FindByNameAndEIdReqDTO.filter(this.enterpriseId, unExist)));
    }

    /**
     * 获取部门列表
     *
     * @param names names
     * @return DepartmentBaseRespDTO 列表
     */
    public List<DepartmentBaseRespDTO> getDepartmentBaseByNames(Collection<String> names) {
        return this.convertList(
                departmentBaseMap_Name,
                names,
                list -> remoteDepartmentService.findBaseMapByNames(FindByNamesAndEIdReqDTO.filter(this.enterpriseId, list)));
    }

    /**
     * 获取部门列表
     *
     * @param departmentIds departmentIds
     * @param filterDeleted filterDeleted
     * @return DepartmentBaseRespDTO 列表
     */
    public List<DepartmentBaseRespDTO> getDepartmentBases(Collection<Long> departmentIds, boolean filterDeleted) {
        return this.convertList(
                departmentBaseMap,
                departmentIds,
                list -> remoteDepartmentService.findBaseMapByIds(FindByIdsReqDTO.build(departmentIds, filterDeleted))
        );
    }

    /**
     * 获取部门列表
     *
     * @param departmentIds departmentIds
     * @param filterDeleted filterDeleted
     * @return DepartmentBaseRespDTO 列表
     */
    public Map<Long, DepartmentBaseRespDTO> getDepartmentBasesMap(Collection<Long> departmentIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getDepartmentBases(departmentIds, filterDeleted), DepartmentBaseRespDTO::getDepartmentId);
    }

    /**
     * 获取部门控件的默认内容
     *
     * @param permissions permissions
     * @return List
     */
    public List<DepartmentBaseRespDTO> getDepartmentBaseList(List<AppPermissionDTO> permissions) {
        Map<Integer, Map<Long, ?>> integerMapMap = applicationPermissionService
                .convertTypeTarget(applicationPermissionService.convertAppPermission(permissions));

        List<DepartmentBaseRespDTO> departmentBases = new ArrayList<>();
        permissions.forEach(p -> {
            if (integerMapMap.containsKey(p.getPermissionType())) {
                Map<Long, ?> targetMap = integerMapMap.get(p.getPermissionType());
                if (targetMap.containsKey(p.getTargetId())) {
                    Object o = targetMap.get(p.getTargetId());
                    // 兼容一个用户拥有多部门的情况
                    if (o instanceof List) {
                        List<?> list = (List<?>) o;
                        departmentBases.addAll(list.stream().map(e -> (DepartmentBaseRespDTO) e).toList());
                    } else {
                        departmentBases.add((DepartmentBaseRespDTO) targetMap.get(p.getTargetId()));
                    }
                }
            }
        });
        return departmentBases;
    }

    /**
     * 获取登录用户部门列表
     *
     * @return DepartmentBaseRespDTO 列表
     */
    public List<DepartmentBaseRespDTO> getLoginUserDepartmentBases() {
        return this.convert(
                userDepartmentBaseMap,
                userId,
                id -> remoteUserDepartmentService.userDepartmentBases(new UserEnterpriseBaseDTO(enterpriseId, userId))
        );
    }
    // endregion

    // region 角色

    /**
     * 获取角色列表
     *
     * @param roleIds       roleIds
     * @param filterDeleted filterDeleted
     * @return RoleBaseRespDTO 列表
     */
    public List<RoleBaseRespDTO> getRoleBases(Collection<Long> roleIds, boolean filterDeleted) {
        return this.convertList(
                roleBaseMap,
                roleIds,
                list -> remoteRoleService.findBaseMapByIds(FindByIdsReqDTO.build(roleIds, filterDeleted))
        );
    }

    /**
     * 获取角色列表
     *
     * @param roleIds       roleIds
     * @param filterDeleted filterDeleted
     * @return RoleBaseRespDTO 列表
     */
    public Map<Long, RoleBaseRespDTO> getRoleBasesMap(Collection<Long> roleIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getRoleBases(roleIds, filterDeleted), RoleBaseRespDTO::getRoleId);
    }
    // endregion

    // region 文件

    /**
     * 获取文件列表
     *
     * @param fileId fileId
     * @return FileRespDTO 列表
     */
    public FileRespDTO getFileBaseById(Long fileId) {
        return this.convert(fileMap, fileId, unExist -> remoteFileService.findBaseByFileId(unExist));
    }

    /**
     * 获取文件列表
     *
     * @param fileCode fileCode
     * @return FileRespDTO 列表
     */
    public FileRespDTO getFileBaseByCode(String fileCode) {
        return this.convert(fileCodeMap, fileCode, unExist -> remoteFileService.findBaseByFileCode(unExist));
    }

    /**
     * 获取文件列表
     *
     * @param fileIds fileIds
     * @return FileRespDTO 列表
     */
    public List<FileRespDTO> getFileBaseByIds(Collection<Long> fileIds) {
        return this.convertList(fileMap, fileIds, list -> remoteFileService.findBaseMapByFileIds_check(list));
    }

    /**
     * 获取文件列表
     *
     * @param fileCodes fileCodes
     * @return FileRespDTO 列表
     */
    public List<FileRespDTO> getFileBaseByCodes(Collection<String> fileCodes) {
        return this.convertList(fileCodeMap, fileCodes, list -> remoteFileService.findBaseMapByFileCodes_check(list));
    }

    /**
     * 获取文件列表
     *
     * @param fileIds fileIds
     * @return FileRespDTO 列表
     */
    public Map<Long, FileRespDTO> getFileBaseMapByIds(Collection<Long> fileIds) {
        return StreamUtil.toMapK(this.getFileBaseByIds(fileIds), FileRespDTO::getFileId);
    }

    /**
     * 获取文件列表
     *
     * @param fileCodes fileCodes
     * @return FileRespDTO 列表
     */
    public Map<Long, FileRespDTO> getFileBaseMapByCode(Collection<String> fileCodes) {
        return StreamUtil.toMapK(this.getFileBaseByCodes(fileCodes), FileRespDTO::getFileId);
    }
    // endregion

    // region 应用

    /**
     * 获取应用
     *
     * @param appId appId
     * @return ApplicationInfo
     */
    public ApplicationInfo getAppById(Long appId) {
        return this.convert(
                appMap,
                appId,
                unExist -> applicationInfoService.getBaseMapper().findById(unExist)
        );
    }

    /**
     * 获取应用
     *
     * @param key key
     * @return ApplicationInfo
     */
    public ApplicationInfo getAppByKey(String key) {
        return this.convert(
                appKeyMap,
                key,
                unExist -> applicationInfoService.getBaseMapper().findByKey(unExist)
        );
    }

    /**
     * 获取应用列表
     *
     * @param appIds appIds
     * @return ApplicationInfo 列表
     */
    public List<ApplicationInfo> getAppByIds(Collection<Long> appIds, boolean filterDeleted) {
        return this.convertList(
                appMap,
                appIds,
                list -> applicationInfoService.getBaseMapper().findMapByIds(appIds, filterDeleted)
        );
    }

    /**
     * 获取应用列表
     *
     * @param appIds appIds
     * @return ApplicationInfo 列表
     */
    public Map<Long, ApplicationInfo> getAppMapByIds(Collection<Long> appIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getAppByIds(appIds, filterDeleted), ApplicationInfo::getApplicationId);
    }

    /**
     * 获取应用列表
     *
     * @param keys keys
     * @return ApplicationInfo 列表
     */
    public List<ApplicationInfo> getAppByKeys(Collection<String> keys, boolean filterDeleted) {
        return this.convertList(
                appKeyMap,
                keys,
                list -> applicationInfoService.getBaseMapper().findMapByKeys(keys, filterDeleted)
        );
    }

    /**
     * 获取应用列表
     *
     * @param keys keys
     * @return ApplicationInfo 列表
     */
    public Map<String, ApplicationInfo> getAppMapByKeys(Collection<String> keys, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getAppByKeys(keys, filterDeleted), ApplicationInfo::getApplicationKey);
    }
    // endregion

    // region 表单

    /**
     * 获取表单
     *
     * @param formId formId
     * @return ApplicationForm
     */
    public ApplicationForm getForm(Long formId, boolean unExistThrows) {
        return this.convert(
                formMap,
                formId,
                id -> applicationFormService.getBaseMapper().findById(id),
                unExistThrows
        );
    }

    /**
     * 获取表单
     *
     * @param formId formId
     * @return ApplicationForm
     */
    public ApplicationForm getForm(Long formId) {
        return this.convert(
                formMap,
                formId,
                id -> applicationFormService.getBaseMapper().findById(id)
        );
    }

    /**
     * 获取表单列表
     *
     * @param formIds formIds
     * @return ApplicationForm 列表
     */
    public List<ApplicationForm> getForms(Collection<Long> formIds, boolean filterDeleted) {
        return this.convertList(
                formMap,
                formIds,
                list -> applicationFormService.getBaseMapper().findMapByIds(formIds, filterDeleted)
        );
    }

    /**
     * 获取表单列表
     *
     * @param formIds formIds
     * @return ApplicationForm 列表
     */
    public Map<Long, ApplicationForm> getFormMap(Collection<Long> formIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getForms(formIds, filterDeleted), ApplicationForm::getFormId);
    }

    /**
     * 获取发布版表单列表
     *
     * @param appIds appIds
     * @return ApplicationForm 列表
     */
    public List<ApplicationForm> getReleaseFormByAppIds(Collection<Long> appIds) {
        return this.convertList(
                appReleaseFormMap,
                appIds,
                list -> applicationFormService.getBaseMapper().findMapByAppIdsAndVersion(appIds, ApplicationVersionEnum.RELEASE_VERSION.getId())
        );
    }

    /**
     * 获取发布版表单列表
     *
     * @param appIds appIds
     * @return ApplicationForm 列表
     */
    public Map<Long, ApplicationForm> getReleaseFormMapByAppIds(Collection<Long> appIds) {
        return StreamUtil.toMapK(this.getReleaseFormByAppIds(appIds), ApplicationForm::getApplicationId);
    }
    // endregion

    // region 控件

    /**
     * 获取指定控件
     *
     * @param controlId     controlId
     * @param unExistThrows 不存在是否抛出异常
     * @return ApplicationFormControl
     */
    public ApplicationFormControl getControl(Long controlId, boolean unExistThrows) {
        return this.convert(
                controlMap,
                controlId,
                id -> applicationFormControlService.findById(controlId),
                unExistThrows
        );
    }

    /**
     * 获取指定控件（redis缓存版）
     *
     * @param controlId     controlId
     * @param unExistThrows 不存在是否抛出异常
     * @return ApplicationFormControl
     */
    public ApplicationFormControl getControl_Cache(Long controlId, boolean unExistThrows) {
        try {
            return applicationFormControlService.getBaseMapper().findById_Cache(controlId);
        } catch (Exception e) {
            if (unExistThrows) {
                throw e;
            }
        }
        return null;
    }

    /**
     * 获取控件列表
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return ApplicationFormControl 列表
     */
    public List<ApplicationFormControl> getControls(Collection<Long> controlIds, boolean filterDeleted) {
        return this.convertList(
                controlMap,
                controlIds,
                list -> applicationFormControlService.getBaseMapper().findMapByIds(controlIds, filterDeleted)
        );
    }

    /**
     * 获取控件列表
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return ApplicationFormControl 列表
     */
    public Map<Long, ApplicationFormControl> getControlMap(Collection<Long> controlIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getControls(controlIds, filterDeleted), ApplicationFormControl::getControlId);
    }

    /**
     * 获取控件
     *
     * @param controlId controlId
     * @return ControlDTO
     */
    public ControlDTO getControlDTO(Long controlId) {
        return this.convert(
                controlDTOMap,
                controlId,
                unExist -> applicationFormControlService.findDTOByControlId(unExist, this)
        );
    }

    /**
     * 获取控件列表
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return ControlDTO 列表
     */
    public List<ControlDTO> getControlDTOs(Collection<Long> controlIds, boolean filterDeleted) {
        return this.convertList(
                controlDTOMap,
                controlIds,
                list -> applicationFormControlService.findDTOMapByControlIds(controlIds, filterDeleted)
        );
    }

    /**
     * 获取控件列表
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return ApplicationFormControl 列表
     */
    public Map<Long, ControlDTO> getControlDTOMap(Collection<Long> controlIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getControlDTOs(controlIds, filterDeleted), ControlDTO::getControlId);
    }

    /**
     * 获取控件列表
     *
     * @param controlId controlId
     * @return ControlBaseInfoDTO
     */
    public ControlBaseDTO getControlBase(Long controlId) {
        return this.convert(
                controlBaseMap,
                controlId,
                id -> applicationFormControlService.findBaseById(id)
        );
    }

    /**
     * 获取控件列表
     *
     * @param controlIds controlIds
     * @return ControlBaseInfoDTO 列表
     */
    public List<ControlBaseDTO> getControlBases(Collection<Long> controlIds) {
        return this.convertList(
                controlBaseMap,
                controlIds,
                list -> applicationFormControlService.findBaseMapByIds(controlIds),
                false
        );
    }

    /**
     * 获取控件列表
     *
     * @param controlIds controlIds
     * @return ControlBaseInfoDTO 列表
     */
    public List<ControlBaseInfoDTO> getControlBaseInfos(Collection<Long> controlIds) {
        return this.convertList(
                controlBaseInfoMap,
                controlIds,
                list -> applicationFormControlService.findBaseInfoMapByControlIds(controlIds),
                false
        );
    }

    /**
     * 获取控件列表
     *
     * @param controlIds controlIds
     * @return ControlBaseInfoDTO 列表
     */
    public Map<Long, ControlBaseInfoDTO> getControlBaseInfoMap(Collection<Long> controlIds) {
        return StreamUtil.toMapK(this.getControlBaseInfos(controlIds), ControlBaseInfoDTO::getControlId);
    }

    // endregion

    // region 控件关联
    public List<ControlRelatedDTO> getControlRelatedBases(Long controlId) {
        return this.convert(
                controlRelatedBasesMap,
                controlId,
                id -> applicationFormControlRelatedService.findBaseByControlId(id, true)
        );
    }
    // endregion

    // region 控件选项

    /**
     * 获取控件列表
     *
     * @param optionId optionId
     * @return FormOptionRespDTO 列表
     */
    public FormOptionRespDTO getOptionById(Long optionId) {
        return this.convert(
                optionMap,
                optionId,
                unExist -> formControlOptionService.findBaseById(unExist)
        );
    }

    /**
     * 获取控件列表
     *
     * @param optionIds     optionIds
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    public List<FormOptionRespDTO> getOptionByIds(Collection<Long> optionIds, boolean filterDeleted) {
        return this.convertList(
                optionMap,
                optionIds,
                list -> formControlOptionService.findBaseMapByIds(optionIds, filterDeleted)
        );
    }

    /**
     * 获取控件列表
     *
     * @param optionIds     optionIds
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    public Map<Long, FormOptionRespDTO> getOptionMapByIds(Collection<Long> optionIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getOptionByIds(optionIds, filterDeleted), FormOptionRespDTO::getOptionId);
    }

    /**
     * 获取控件选项列表
     *
     * @param controlId     controlId
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    public List<FormOptionRespDTO> getOptionByControlId(Long controlId, boolean filterDeleted) {
        return this.convert(
                controlOptionMap,
                controlId,
                id -> formControlOptionService.findBaseByControlId(id, filterDeleted)
        );
    }

    /**
     * 获取控件选项列表
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    public Map<Long, List<FormOptionRespDTO>> getOptionMapByControlIds(Collection<Long> controlIds, boolean filterDeleted) {
        return this.convertMap(
                controlOptionMap,
                controlIds,
                list -> formControlOptionService.findBasesByControlIds(list, filterDeleted),
                false
        );
    }
    // endregion

    // region 流程

    /**
     * 获取表单列表
     *
     * @param processIds processIds
     * @return ApplicationProcess 列表
     */
    public List<ApplicationProcess> getProcess(Collection<Long> processIds, boolean filterDeleted) {
        return this.convertList(
                processMap,
                processIds,
                list -> applicationProcessService.getBaseMapper().findMapByIds(processIds, filterDeleted)
        );
    }

    /**
     * 获取表单列表
     *
     * @param processIds processIds
     * @return ApplicationProcess 列表
     */
    public Map<Long, ApplicationProcess> getProcessMap(Collection<Long> processIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getProcess(processIds, filterDeleted), ApplicationProcess::getProcessId);
    }

    /**
     * 获取发布版表单列表
     *
     * @param appIds appIds
     * @return ApplicationProcess 列表
     */
    public List<ApplicationProcess> getReleaseProcessByAppIds(Collection<Long> appIds) {
        return this.convertList(
                appReleaseProcessMap,
                appIds,
                list -> applicationProcessService.getBaseMapper().findMapByAppIdsAndVersion(appIds, ApplicationVersionEnum.RELEASE_VERSION.getId())
        );
    }

    /**
     * 获取发布版表单列表
     *
     * @param appIds appIds
     * @return ApplicationProcess 列表
     */
    public Map<Long, ApplicationProcess> getReleaseProcessMapByAppIds(Collection<Long> appIds) {
        return StreamUtil.toMapK(this.getReleaseProcessByAppIds(appIds), ApplicationProcess::getApplicationId);
    }
    // endregion

    // region 流程节点

    /**
     * 获取节点基础信息列表
     *
     * @param nodeIds       nodeIds
     * @param filterDeleted filterDeleted
     * @return NodeBaseDTO 列表
     */
    public List<NodeBaseDTO> getByNodeIds(Collection<Long> nodeIds, boolean filterDeleted) {
        return this.convertList(
                nodeMap,
                nodeIds,
                list -> applicationProcessNodeService.findBaseMapByIds(list, filterDeleted)
        );
    }

    /**
     * 获取节点基础信息列表
     *
     * @param nodeIds       nodeIds
     * @param filterDeleted filterDeleted
     * @return NodeBaseDTO 列表
     */
    public Map<Long, NodeBaseDTO> getMapByNodeIds(Collection<Long> nodeIds, boolean filterDeleted) {
        return StreamUtil.toMapK(this.getByNodeIds(nodeIds, filterDeleted), NodeBaseDTO::getNodeId);
    }
    // endregion

    // region 权限

    /**
     * 获取应用权限
     *
     * @param source source
     * @return AppPermissionDTO 列表
     */
    public List<AppPermissionDTO> findBySource(AppPermissionSourceDTO source) {
        return this.convert(
                sourceAppPermissionsMap,
                source,
                s -> applicationPermissionService.findDTOBySource(s)
        );
    }

    /**
     * 获取应用权限
     *
     * @param sources sources
     * @return AppPermissionDTO 列表
     */
    public Map<AppPermissionSourceDTO, List<AppPermissionDTO>> findBySources(Collection<AppPermissionSourceDTO> sources) {
        return this.convertMap(
                sourceAppPermissionsMap,
                sources,
                list -> applicationPermissionService.findDTOMapBySources(list),
                false
        );
    }
    // endregion

    // region 条件

    /**
     * 获取条件列表
     *
     * @param source source
     * @return JudgeOr 列表
     */
    public List<JudgeOr> getJudgeBySource(JudgeSourceDTO source) {
        return this.convert(
                sourcesJudgeMap,
                source,
                s -> applicationJudgeService.findDTOBySource(s)
        );
    }

    /**
     * 获取条件列表
     *
     * @param sources sources
     * @return JudgeOr 列表
     */
    public Map<JudgeSourceDTO, List<JudgeOr>> getJudgeMapBySource(Collection<JudgeSourceDTO> sources) {
        return this.convertMap(
                sourcesJudgeMap,
                sources,
                list -> applicationJudgeService.findDTOMapBySources(list),
                false
        );
    }
    // endregion

    // region 订单

    /**
     * 获取订单
     *
     * @param orderId orderId
     * @return List
     */
    public ApplicationOrder getOrder(Long orderId) {
        return this.convert(orderMap, orderId, unExist -> applicationOrderService.getBaseMapper().findById(unExist));
    }

    /**
     * 获取关联选项
     *
     * @param orderDataIds orderDataIds
     * @return List
     */
    public List<FormOptionRespDTO> getQuoteSelects(List<Long> orderDataIds) {
        return this.convertList(orderQuoteMap, orderDataIds, unExistList -> applicationOrderDataService.orderRelatedSelectMap(unExistList, this), false);
    }

    /**
     * 获取关联选项
     *
     * @param orderDataId orderDataId
     * @return List
     */
    public FormOptionRespDTO getQuoteSelects(Long orderDataId) {
        return this.convert(orderQuoteMap, orderDataId, unExist -> applicationOrderDataService.orderRelatedSelect(unExist, this));
    }

    /**
     * 获取订单节点处理人
     *
     * @param orderNodes orderNodes
     * @return List
     */
    public Map<String, List<ApplicationOrderNodeHandler>> getOrderNodeHandlerMap(@Valid OrderNodesDTO orderNodes) {
        List<Long> nodeIds = StreamUtil.filter(orderNodes.getNodeIds(), nodeId -> ApplicationUtil.DEFAULT_NODE_ID.compareTo(nodeId) < 0);
        if (nodeIds.isEmpty()) {
            return new HashMap<>();
        }
        orderNodes.setNodeIds(nodeIds);
        return this.convertMap(orderNodeHandlerMap, ApplicationUtil.orderNodeKeys(orderNodes), unExist ->
                applicationOrderNodeHandlerService.getBaseMapper().orderNodesHandlersMap(ApplicationUtil.restoreOrderNodeKeys(unExist)), false);
    }

    /**
     * 订单控件数据 控件类型
     *
     * @param orderData orderData
     * @return ControlCodeEnum
     */
    public ControlCodeEnum getControlCodeByOrderData(ApplicationOrderData orderData) {
        // 获取该数据对应控件类型 （先判断是否为特殊控件情况）
        return OrderSpecialControlEnum.isExistById(orderData.getControlId())
                .map(OrderSpecialControlEnum::getControlCode)
                .orElseGet(() -> {
                    // 获取表单控件
                    ApplicationFormControl control = this.getControl(orderData.getControlId(), true);
                    return ControlCodeEnum.findByCode(control.getControlCode());
                });
    }

    /**
     * 缓存订单数据需要的 文件、人员、部门、选项、引用
     *
     * @param orderDataList orderDataList
     */
    public void cacheOrderData(Collection<ApplicationOrderData> orderDataList) {
        orderDataList = StreamUtil.filter(orderDataList, e -> !OrderSpecialControlEnum.isSpecialControlId(e.getControlId()));
        List<String> fileCodes = new ArrayList<>();
        List<Long> userIds = new ArrayList<>();
        List<Long> deptIds = new ArrayList<>();
        List<Long> optionIds = new ArrayList<>();
        List<Long> orderDataIds = new ArrayList<>();
        List<Long> controlIds = StreamUtil.transListT(orderDataList, ApplicationOrderData::getControlId);
        this.getControls(controlIds, false);

        for (ApplicationOrderData orderData : orderDataList) {
            ApplicationFormControl control = controlMap.get(orderData.getControlId());
            if (Objects.isNull(control)) {
                // 数据库不存在的控件一律忽略
                continue;
            }
            ControlCodeEnum controlCodeEnum = ControlCodeEnum.findByCode(control.getControlCode());
            // 数据收集-上传控件
            if (ControlCodeEnum.UPLOAD.getCode().equals(controlCodeEnum.getCode())) {
                fileCodes.addAll(OrderDataUtil.getOrderDataValues(JSON.parseArray(orderData.getOrderData(), ControlDataValueDTO.class)));
            }
            // 数据收集-人员选择控件
            else if (ControlCodeEnum.MEMBER_SEL.getCode().equals(controlCodeEnum.getCode())) {
                userIds.addAll(OrderDataUtil.getControlValueIds(JSON.parseArray(orderData.getOrderData(), ControlDataValueDTO.class)));
            }
            // 数据收集-部门选择控件
            else if (ControlCodeEnum.DEPT_SEL.getCode().equals(controlCodeEnum.getCode())) {
                deptIds.addAll(OrderDataUtil.getControlValueIds(JSON.parseArray(orderData.getOrderData(), ControlDataValueDTO.class)));
            }
            // 有下拉项控件
            else if (controlCodeEnum.hasOptions()) {
                optionIds.addAll(OrderDataUtil.getControlValueIds(JSON.parseArray(orderData.getOrderData(), ControlDataValueDTO.class)));
            }
            // 有引用
            else if (controlCodeEnum.hasQuote()) {
                orderDataIds.addAll(OrderDataUtil.getControlValueIds(JSON.parseArray(orderData.getOrderData(), ControlDataValueDTO.class)));
            }
        }
        this.getFileBaseByCodes(fileCodes);
        this.getUserBases(userIds, false);
        this.getDepartmentBases(deptIds, false);
        this.getOptionByIds(optionIds, false);
        this.getQuoteSelects(orderDataIds);
    }

    /**
     * 获取订单数据Bean 值
     *
     * @param applicationOrder  订单
     * @param orderData         订单控件Bean
     * @param perfect           是否完善信息
     * @param filterCurrentNode 是否过滤当前节点
     * @return List
     */
    public List<ControlDataValueDTO> initOrderDataValues(ApplicationOrder applicationOrder, ApplicationOrderData orderData, boolean perfect, boolean filterCurrentNode) {
        return this.initOrderData(applicationOrder, orderData, perfect, filterCurrentNode).getValues();
    }

    /**
     * 转换订单数据Bean 为控件数据实体
     *
     * @param applicationOrder  订单
     * @param orderData         订单控件Bean
     * @param perfect           是否完善信息
     * @param filterCurrentNode 是否过滤当前节点
     * @return ControlDataDTO
     */
    public ControlDataDTO initOrderData(ApplicationOrder applicationOrder, ApplicationOrderData orderData, boolean perfect, boolean filterCurrentNode) {
        ApplicationOrder order = Objects.nonNull(applicationOrder) ? applicationOrder : this.getOrder(orderData.getOrderId());

        SpecialControlData specialControlData = BeanUtil.copyProperties(order, SpecialControlData.class);
        // 初始化控件数据
        ControlDataDTO controlData = OrderSpecialControlEnum.isExistById(orderData.getControlId())
                .map(e -> {
                    // 特殊控件
                    ApplicationForm form = applicationFormService.getBaseMapper().findByAppIdAndVersion(order.getApplicationId(),
                            ApplicationVersionEnum.RELEASE_VERSION.getId());
                    SpecialControlConfigDTO specialControlConfigDTO = ApplicationUtil.specialControlConfig(form.getSpecialControlConfig());
                    return e.createControlData(specialControlConfigDTO, specialControlData, this::getUserBase);
                })
                .orElseGet(() -> {
                    // 表单控件
                    ApplicationFormControl control = this.getControl(orderData.getControlId(), true);
                    return ApplicationUtil.controlToControlData(control);
                });
        controlData.setOrderDataId(orderData.getOrderDataId());
        controlData.setSort(orderData.getSort());
        controlData.setValues(JSON.parseArray(orderData.getOrderData(), ControlDataValueDTO.class));
        // 完善信息
        if (perfect) {
            this.initOrderDataValues(applicationOrder, controlData, filterCurrentNode);
        }
        return controlData;
    }

    /**
     * 构造初始化订单节点数据
     *
     * @param applicationOrder  applicationOrder
     * @param controlData       controlData
     * @param filterCurrentNode 是否过滤 当前登陆人可见 处理节点
     */
    public void initOrderDataValues(ApplicationOrder applicationOrder, ControlDataDTO controlData, boolean filterCurrentNode) {
        ControlCodeEnum controlCodeEnum = ControlCodeEnum.findByCode(controlData.getControlCode());
        List<ControlDataValueDTO> dataValues = controlData.getValues();
        if (null != applicationOrder) {
            if (OrderSpecialControlEnum.NODE.getId().equals(controlData.getControlId())) {
                if (!dataValues.isEmpty()) {
                    // 订单所有处理人
                    OrderNodesDTO orderNodes = new OrderNodesDTO(applicationOrder.getOrderId(), OrderDataUtil.getControlValueIds(dataValues));
                    Map<String, List<ApplicationOrderNodeHandler>> nodeHandlerMap = this.getOrderNodeHandlerMap(orderNodes);
                    // 已处理 处理类型集合
                    List<Integer> handledTypes = HandleTypeEnum.getHandledType();
                    dataValues = dataValues.stream()
                            // 是否过滤 当前登陆人可见 处理节点
                            .filter(e -> {
                                String orderNodeKey = ApplicationUtil.orderNodeKey(applicationOrder.getOrderId(), e.getId());
                                // 节点处理人
                                List<ApplicationOrderNodeHandler> currentDataNodeHandler = nodeHandlerMap.getOrDefault(orderNodeKey, new ArrayList<>());
                                if (!filterCurrentNode) {
                                    // 不过滤待办节点 则需要过滤已处理的（补充解释：全部数据tab 不返回已处理的节点）
                                    return currentDataNodeHandler.stream().anyMatch(h -> !handledTypes.contains(h.getHandleType()));
                                }
                                // 过滤待办节点 则只显示我待处理节点
                                return currentDataNodeHandler.stream().anyMatch(h -> h.getHandlerId().equals(userId) && !handledTypes.contains(h.getHandleType()));
                            })
                            .collect(Collectors.toList());

                    // 获取节点
                    this.getByNodeIds(OrderDataUtil.getControlValueIds(dataValues), false);
                }
                dataValues = OrderProcessStatusEnum.findById(applicationOrder.getProcessStatus()).nodeNameConvert(dataValues, nodeMap);
                controlData.setValues(dataValues);
                return;
            }
            // 数据处理-行容器|编辑器|表格|标签页
            else if (ControlCodeEnum.isNeedDetailShow(controlCodeEnum.getCode())) {
                dataValues = ListUtil.toList(new ControlDataValueDTO(ApplicationUtil.CLICK_LOOK_DETAIL));
                if (ControlCodeEnum.TABLE.getCode().equals(controlCodeEnum.getCode())) {
                    controlData.getTableValues().forEach(row -> row.forEach(cell -> this.initOrderDataValues(applicationOrder, cell, filterCurrentNode)));
                }
            }
        }
        this.initOrderDataValues(controlCodeEnum, dataValues);
        controlData.setValues(dataValues);
    }

    public void initOrderDataValues(ControlCodeEnum controlCodeEnum, List<ControlDataValueDTO> dataValues) {
        dataValues.forEach(dataValue -> this.initOrderDataValue(controlCodeEnum, dataValue));
    }

    public void initOrderDataValues(ControlDataDTO controlData) {
        ControlCodeEnum controlCodeEnum = ControlCodeEnum.findByCode(controlData.getControlCode());
        controlData.getValues().forEach(dataValue -> this.initOrderDataValue(controlCodeEnum, dataValue));
    }

    public void initOrderDataValue(ControlCodeEnum controlCodeEnum, ControlDataValueDTO dataValue) {
        // 数据收集-上传控件
        if (ControlCodeEnum.UPLOAD.getCode().equals(controlCodeEnum.getCode())) {
            dataValue.setOtherInfo(this.getFileBaseByCode(dataValue.getValue()));
        }
        // 数据收集-人员选择控件
        else if (ControlCodeEnum.MEMBER_SEL.getCode().equals(controlCodeEnum.getCode())) {
            dataValue.setOtherInfo(this.getUserBase(dataValue.getId()));
        }
        // 数据收集-部门选择控件
        else if (ControlCodeEnum.DEPT_SEL.getCode().equals(controlCodeEnum.getCode())) {
            dataValue.setOtherInfo(this.getDepartmentBase(dataValue.getId()));
        }
        // 有下拉项控件
        else if (controlCodeEnum.hasOptions()) {
            if (CollectionUtil.isNotEmpty(dataValue.getIds())) {
                dataValue.setOtherInfo(this.getOptionByIds(dataValue.getIds(), false));
            } else {
                dataValue.setOtherInfo(this.getOptionById(dataValue.getId()));
            }
        }
        // 有引用
        else if (controlCodeEnum.hasQuote()) {
            dataValue.setOtherInfo(this.getQuoteSelects(dataValue.getId()));
        }
    }
    // endregion

    // region convert
    private <K, V> V convert(Map<K, V> map, K k, Function<K, V> get) {
        return this.convert(map, k, get, true);
    }

    private <K, V> V convert(Map<K, V> map, K k, Function<K, V> get, boolean unExistThrows) {
        this.checkInit(map);
        if (map.containsKey(k)) {
            return map.get(k);
        } else {
            V v = null;
            try {
                v = get.apply(k);
            } catch (Exception exception) {
                if (unExistThrows) {
                    throw exception;
                }
            }
            if (Objects.nonNull(v)) {
                map.put(k, v);
            }
            return v;
        }
    }

    private <K, V> List<V> convertList(Map<K, V> map, Collection<K> list, Function<List<K>, Map<K, V>> get) {
        return this.convertList(map, list, get, true);
    }

    private <K, V> List<V> convertList(Map<K, V> map, Collection<K> list, Function<List<K>, Map<K, V>> get, boolean unExistThrows) {
        return new ArrayList<>(this.convertMap(map, list, get, unExistThrows).values());
    }

    private <K, V> Map<K, V> convertMap(Map<K, V> map, Collection<K> list, Function<List<K>, Map<K, V>> get, boolean unExistThrows) {
        this.checkInit(map);
        if (list.isEmpty()) {
            return new HashMap<>();
        }
        // 不存在列表
        List<K> unExistList = list.stream().filter(e -> !map.containsKey(e)).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(unExistList)) {
            // 重新获取不存在
            map.putAll(get.apply(unExistList));
        }

        // 错误记录
        List<String> errorMsg = new ArrayList<>();
        // 返回
        Map<K, V> result = new HashMap<>();
        list.forEach(e -> {
            if (map.containsKey(e)) {
                result.put(e, map.get(e));
            } else {
                errorMsg.add(String.format("[%s] 不存在", e));
            }
        });
        // 是否排除不存在错误
        if (unExistThrows && !errorMsg.isEmpty()) {
            throw new BusinessException(BaseEnum.RUN_ERROR, String.join("，", errorMsg));
        }
        return result;
    }

    private <K, V> void checkInit(Map<K, V> map) {
        if (null == map) {
            throw new BusinessException(BaseEnum.RUN_ERROR, "map not init");
        }
    }
    // endregion
}
